<?php

namespace process;

use Workerman\Crontab\Crontab;
use Workerman\Timer;
use app\bll\CrontabTask as BllCrontabTask;
use ReflectionClass;

class Task
{
    /**
     * 当 Worker 启动时执行的方法
     * 该方法会定时检查是否需要重新加载定时任务。它会在 Worker 启动后的每 3 秒执行一次检查逻辑，
     * 若满足条件则会清空现有的定时任务，并从数据库中读取新的定时任务进行加载。
     */
    public function onWorkerStart()
    {
        // 初始化标志，用于判断是否是第一次执行
        $init = true;
        // 每 50 秒执行一次回调函数
        Timer::add(50, function () use ($init) {
            // 定义定时任务锁文件的路径
            $cronLockFile = runtime_path() . '/crontabtask.lock';
            // 检查锁文件是否不存在或者是第一次执行
            if (
                (!file_exists($cronLockFile) || $init)
                && !file_exists(base_path() . '/install.lock')
            ) {

                // 创建锁文件，加锁防止重复加载定时任务
                file_put_contents($cronLockFile, '');
                // 标记初始化已完成
                $init = false;

                // 获取所有已存在的定时任务
                $crontabs = Crontab::getAll();
                // 遍历所有定时任务并移除
                foreach ($crontabs as $crontab) {
                    Crontab::remove($crontab);
                }

                // 创建 BllCrontabTask 类的实例
                $bllCrontabTask = new BllCrontabTask();
                // 从数据库中查询所有定时任务
                $tasks = $bllCrontabTask->select(1);
                // 遍历查询到的定时任务
                foreach ($tasks as $task) {
                    // 创建新的定时任务
                    new Crontab($task['rule'], function () use ($task) {
                        switch ($task['tasktype']) {
                            case 1:
                                // 使用反射机制创建事件类的反射类实例
                                list($event, $class, $method) = explode('/', $task['event']);
                                $reflectionClass = new ReflectionClass(
                                    '\\component\\event\\' . $event . '\\' . $class
                                );
                                break;
                            case 2: //自定义
                                // 使用反射机制创建事件类的反射类实例
                                $events     = trim(str_replace('/', '\\', $task['event']), '\\');
                                $events_arr = explode('\\', $events);
                                $classpath  = '';
                                for ($i = 0; $i < count($events_arr); $i++) {
                                    if ($i == count($events_arr) - 1) {
                                        $method = $events_arr[$i];
                                    } else {
                                        $classpath .= '\\' . $events_arr[$i];
                                    }
                                }

                                $reflectionClass = new ReflectionClass(
                                    $classpath
                                );

                                break;
                        }



                        // 获取事件类的 dispatch 方法
                        $method = $reflectionClass->getMethod($method);
                        // 检查 dispatch 方法是否为公共方法
                        if ($method->isPublic()) {
                            // 创建事件类的实例
                            $instance = $reflectionClass->newInstance();
                            // 调用实例的 dispatch 方法并传入空数组作为参数
                            $method->invoke($instance, []);
                        }
                        // 输出当前时间
                    });
                }
            }
        });
    }
}
